Skip to content

UserIconFrameClass.jsxをバニラJS化#9030

Merged
komagata merged 4 commits intomainfrom
chore/convert-user-icon-frame-class-to-vanilla-js
Nov 4, 2025
Merged

UserIconFrameClass.jsxをバニラJS化#9030
komagata merged 4 commits intomainfrom
chore/convert-user-icon-frame-class-to-vanilla-js

Conversation

@karlley
Copy link
Copy Markdown
Contributor

@karlley karlley commented Aug 14, 2025

Issue

概要

UserIconFrameClass.jsxをバニラJS化

変更確認方法

  1. chore/convert-user-icon-frame-class-to-vanilla-js をローカルに取り込む
  2. データ初期化(テスト用ユーザーを当日の日付で作成するため)
  3. 開発環境起動
git fetch origin chore/convert-user-icon-frame-class-to-vanilla-js
git switch -c chore/convert-user-icon-frame-class-to-vanilla-js 
bundle exec rails db:seed
foreman start -f Procfile.dev
  1. 各ファイル毎に以下の手順で動作確認を行う

Report.jsx

  1. OS X Mountain Lionをクリーンインストールするのプラクティスを選択した日報投稿をkimuraotameshi の2ユーザーで行う
  2. OS X Mountain Lionをクリーンインストールする プラクティスの日報タブを選択(/practice/:id/reports)して以下を確認

それぞれの日報投稿者のアイコンの外側のspanタグのクラスが以下のようになっているか

  • kimura: a-user-role is-student
  • otameshi: a-user-role is-student is-new-user
1

↓User.jsxはmainで削除されました

User.jsx

  1. machida でログインし、ユーザー > 期生別タブを選択(/generations)
  2. 5期生の詳細画面を開く(/generations/5)
  3. kimura ユーザーで以下を確認
  • ユーザーアイコンの外側のspanタグのクラスがa-user-role is-student になっている
  1. 51期生の詳細画面を開く(/generations/51)
  2. otameshi ユーザーで以下を確認
  • ユーザーアイコンの外側のspanタグのクラスがa-user-role is-student is-new-user になっている

2

Notification.jsx、ListComment.jsx

  1. machidaでログインし、日報投稿
  2. machida が投稿した日報へのコメント投稿をkimuraotameshi の2ユーザーで行う
  3. machida でログインし以下を確認

通知プルダウン内のコメント投稿者のアイコンの外側のspanタグのクラスが以下のようになっているか

  • kimura: a-user-role is-student header-notifications-item__user-icon
  • otameshi: a-user-role is-student is-new-user header-notifications-item__user-icon
3

日報一覧(/reports)で日報リスト左の大きいアイコンの外側のspanタグのクラスが以下のようになっているか

  • kimura: a-user-role is-student
  • otameshi: a-user-role is-student is-new-user
4

Summary by CodeRabbit

  • リファクター
    • ユーザーアイコンのスタイリング機能に関わる内部コード構造を改善しました。複数のコンポーネントで共有されるロジックを整理し、コードの保守性と一貫性を向上させました。ユーザーへの表示結果に変更はありません。

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Aug 14, 2025

Walkthrough

UserIconFrameClass React コンポーネント(名前付きエクスポート)をバニラ JavaScript 関数 userIconFrameClass(デフォルトエクスポート)に refactor しました。関数シグネチャが単一のオブジェクト引数から primaryRolejoiningStatus の 2 つのパラメータに変更され、3 つのコンポーネント内の呼び出し箇所が更新されています。

Changes

Cohort / File(s) Summary
新しいユーザーアイコンフレームクラス関数
app/javascript/user-icon-frame-class.js
新しいデフォルトエクスポート関数 userIconFrameClass(primaryRole, joiningStatus) を追加。CSS クラス文字列を計算し、is-${primaryRole}is-new-user(該当する場合)を含める。
コンポーネント内の import 更新
app/javascript/components/ListComment.jsx, app/javascript/components/NotificationsBell/Notifications.jsx, app/javascript/components/Report.jsx
名前付き import { UserIconFrameClass } をデフォルト import userIconFrameClass に変更。呼び出し方法を単一オブジェクト引数から primaryRolejoiningStatus の 2 引数に変更。
削除
app/javascript/components/UserIconFrameClass.jsx
元の UserIconFrameClass React コンポーネントを削除。

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • 関数シグネチャ変更が一貫して 3 つの呼び出し箇所に適用されている同じパターンの refactor
  • 新しい関数ロジックの妥当性を確認(クラス文字列生成ロジック)
  • 削除されたファイルと新しいファイルの対応確認

Possibly related issues

Possibly related PRs

Suggested reviewers

  • komagata

Poem

🐰 ウサギがクラスを refactor して、
React から vanilla へと移り歩き、
二つの引数で優雅に踊り、
CSS フレームは光り輝く。
コンポーネント三つが新しい道を歩む、
✨ より clean で、より fast に!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed プルリクエストのタイトル「UserIconFrameClass.jsxをバニラJS化」は、変更内容の主要な点を明確に表現しています。React JSXコンポーネントからバニラJavaScriptへの変換というこのPRの中核的な目的を正確に反映しており、チームメンバーが履歴をスキャンする際に主要な変更内容を即座に理解できる内容です。タイトルは簡潔で具体的、かつノイズのないものとなっています。
Description Check ✅ Passed PR説明にはテンプレートで要求されるすべての必須セクション(Issue番号 #9008、概要「UserIconFrameClass.jsxをバニラJS化」、詳細な変更確認方法)が適切に記載されており、複数のスクリーンショットも添付されている。テンプレートで明示的に分離が求められている「## Screenshot」というトップレベルセクションが独立していないものの、実際には各機能ごと(Report.jsx、Notification.jsx、ListComment.jsx)の確認手順の直後に対応するスクリーンショットが配置され、変更結果を視覚的に十分に確認できる構成になっており、むしろテンプレート以上に詳細でわかりやすい説明となっている。
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/convert-user-icon-frame-class-to-vanilla-js

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@karlley karlley marked this pull request as ready for review August 14, 2025 23:02
@github-actions github-actions bot requested a review from komagata August 14, 2025 23:02
@karlley karlley changed the title Chore/convert user icon frame class to vanilla js UserIconFrameClass.jsxをバニラJS化 Aug 14, 2025
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
app/javascript/user-icon-frame-class.js (1)

1-5: 未定義値への耐性と余分なスペースを避ける実装にすると堅牢性が上がります(任意)

user が null/undefined の場合や、joining_status が未設定の場合でも安全にクラスを組み立てるようにしておくと将来の変更に強くなります。配列で組み立てると余分な空白も出ません。

適用例:

-export default function userIconFrameClass(user) {
-  return `a-user-role is-${user.primary_role} ${
-    user.joining_status === 'new-user' ? 'is-new-user' : ''
-  }`
-}
+export default function userIconFrameClass(user) {
+  const role = user?.primary_role
+  const isNew = user?.joining_status === 'new-user'
+  return ['a-user-role', role && `is-${role}`, isNew && 'is-new-user']
+    .filter(Boolean)
+    .join(' ')
+}
app/javascript/components/User.jsx (1)

28-28: 同じクラス計算の重複呼び出しを避ける(任意)

同一引数に対し 2 回呼び出しているので、可読性とわずかなパフォーマンス向上のために一度だけ計算して再利用するのを推奨します。

例:

export default function User({ user, currentUser }) {
  const userIconClass = userIconFrameClass(user)
  // ...
  <div className={`users-item__inner a-card ${userIconClass}`}>
  // ...
  <span className={userIconClass}>
    <img ... />
  </span>
}

Also applies to: 56-56

app/javascript/components/NotificationsBell/Notifications.jsx (1)

61-63: 通知アイコンの alt を具体的に(任意)

アクセシビリティ向上のため、送信者名など意味のある代替テキスト/タイトルにすることを推奨します。

例:

<img
  src={notification.sender.avatar_url}
  className="a-user-icon"
  title={notification.sender.login_name}
  alt={notification.sender.login_name}
/>
app/javascript/components/ListComment.jsx (1)

24-26: コメントのユーザーアイコンに alt 付与を検討(任意)

アクセシビリティのため、可能ならユーザー名等の alt を付与してください(API 形状が未確定の場合は a 要素に aria-label を付けるのも可)。

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 30a74a9 and 95980fe.

📒 Files selected for processing (5)
  • app/javascript/components/ListComment.jsx (2 hunks)
  • app/javascript/components/NotificationsBell/Notifications.jsx (2 hunks)
  • app/javascript/components/Report.jsx (2 hunks)
  • app/javascript/components/User.jsx (3 hunks)
  • app/javascript/user-icon-frame-class.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js

⚙️ CodeRabbit Configuration File

**/*.js: - どうしても避けられない時以外に新規にVue.js, Reactのコードを追加しない。

  • fetchメソッドの代わりにrequest.jsを使う。

Files:

  • app/javascript/user-icon-frame-class.js
🧬 Code Graph Analysis (4)
app/javascript/components/NotificationsBell/Notifications.jsx (1)
app/javascript/user-icon-frame-class.js (1)
  • userIconFrameClass (1-5)
app/javascript/components/Report.jsx (1)
app/javascript/user-icon-frame-class.js (1)
  • userIconFrameClass (1-5)
app/javascript/components/User.jsx (1)
app/javascript/user-icon-frame-class.js (1)
  • userIconFrameClass (1-5)
app/javascript/components/ListComment.jsx (1)
app/javascript/user-icon-frame-class.js (1)
  • userIconFrameClass (1-5)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build_and_test
🔇 Additional comments (6)
app/javascript/user-icon-frame-class.js (2)

1-5: default export への移行は問題ありません

コンポーネント側の import 変更と整合しており、挙動はそのまま維持されます。


1-5: UserIconFrameClass の残存参照は見つかりませんでした(確認済み)

ripgrep でリポジトリ全体を検索し、シンボル名および import/require によるパス参照を確認しましたが一致はありませんでした。対象ファイル: app/javascript/user-icon-frame-class.js

app/javascript/components/Report.jsx (1)

3-3: import と使用箇所の置換は妥当です

新しい default export の利用に揃っており、従来ロジックのままです。

Also applies to: 73-73

app/javascript/components/User.jsx (1)

7-7: API 切り替えは妥当です

import/使用箇所ともに新しい default export に統一されており、期待どおりです。

Also applies to: 28-28, 56-56

app/javascript/components/NotificationsBell/Notifications.jsx (1)

5-5: import と使用箇所の置換は妥当です

通知アイテムでも新しいユーティリティに統一されています。

Also applies to: 61-63

app/javascript/components/ListComment.jsx (1)

2-2: import の置換は妥当です

default export に揃っており問題ありません。

Comment on lines 24 to 26
<span className={userIconFrameClass(comment)}>
<img className="a-user-icon" src={comment.user_icon}/>
</span>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Aug 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

comment を渡している点を要確認:userIconFrameClass は user 形状を前提

ListComment だけ userIconFrameClass(comment) を渡しています。他ファイルは user/sender を渡しており、comment オブジェクトに primary_rolejoining_status が存在しない場合、is-undefined 等のクラスが出力される恐れがあります。API 形状を確認してください。

形状が保証されない場合の対処案:

  • A. 必要最小限のフィールドだけを渡す
-<span className={userIconFrameClass(comment)}>
+<span
+  className={userIconFrameClass({
+    primary_role: comment.primary_role,
+    joining_status: comment.joining_status
+  })}
+>
  • B. ユーティリティ側で user-like を受け入れるよう防御的に実装(app/javascript/user-icon-frame-class.js の提案と整合)

検証用スクリプト(comment に必要フィールドが含まれる前提箇所を捜索):


🏁 Script executed:

#!/bin/bash
# comment と primary_role/joining_status の同居をリポジトリ横断で調査
rg -n -C3 -P 'comment[s]?\b.*\b(primary_role|joining_status)\b'

Length of output: 734


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for symbol usages ==="
rg -n --hidden -S "userIconFrameClass" || true
rg -n --hidden -S "user-icon-frame-class" || true
rg -n --hidden -S "userIconFrame" || true

echo
echo "=== Show app/javascript/components/ListComment.jsx ==="
if [ -f app/javascript/components/ListComment.jsx ]; then
  nl -ba app/javascript/components/ListComment.jsx | sed -n '1,240p'
else
  echo "file not found: app/javascript/components/ListComment.jsx"
fi

echo
echo "=== Try common utility paths for user icon frame class ==="
for f in \
  app/javascript/user-icon-frame-class.js \
  app/javascript/user_icon_frame_class.js \
  app/javascript/lib/user-icon-frame-class.js \
  app/javascript/utils/user-icon-frame-class.js \
  app/javascript/user-icon-frame-class.jsx \
  app/javascript/components/user-icon-frame-class.js; do
  if [ -f "$f" ]; then
    echo "---- $f ----"
    nl -ba "$f" | sed -n '1,240p'
  fi
done

echo
echo "=== Search where primary_role / joining_status appear ==="
rg -n -S --hidden -C3 'primary_role|joining_status' || true

Length of output: 3121


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- app/javascript/user-icon-frame-class.js ----"
if [ -f app/javascript/user-icon-frame-class.js ]; then
  sed -n '1,240p' app/javascript/user-icon-frame-class.js
else
  echo "NOT FOUND"
fi

echo
echo "---- app/javascript/components/ListComment.jsx ----"
if [ -f app/javascript/components/ListComment.jsx ]; then
  sed -n '1,240p' app/javascript/components/ListComment.jsx
else
  echo "NOT FOUND"
fi

echo
echo "---- app/javascript/components/User.jsx ----"
if [ -f app/javascript/components/User.jsx ]; then
  sed -n '1,240p' app/javascript/components/User.jsx
else
  echo "NOT FOUND"
fi

echo
echo "---- app/javascript/components/Report.jsx ----"
if [ -f app/javascript/components/Report.jsx ]; then
  sed -n '1,240p' app/javascript/components/Report.jsx
else
  echo "NOT FOUND"
fi

echo
echo "---- app/javascript/components/NotificationsBell/Notifications.jsx ----"
if [ -f app/javascript/components/NotificationsBell/Notifications.jsx ]; then
  sed -n '1,240p' app/javascript/components/NotificationsBell/Notifications.jsx
else
  echo "NOT FOUND"
fi

echo
echo "---- Search for primary_role / joining_status in JS ----"
rg -n --hidden -S --js 'primary_role|joining_status' || true

Length of output: 16710


要修正: ListComment が user 形状前提の userIconFrameClass に comment を渡している

user-icon-frame-class.js は user.primary_role / user.joining_status を参照する実装です。確認結果:

  • app/javascript/user-icon-frame-class.js はこれらのフィールドを前提にクラスを組み立てている
  • 他コンポーネントは user / sender を渡しているが、app/javascript/components/ListComment.jsx は comment を渡している(user 情報が含まれない場合がある)

該当箇所(要修正):

  • app/javascript/components/ListComment.jsx — 現在: ...
  • app/javascript/user-icon-frame-class.js — 現状の実装は user.primary_role を直接参照

対処案(推奨順):

  1. 推奨: ユーティリティを防御的に修正(必須)
--- app/javascript/user-icon-frame-class.js
-export default function userIconFrameClass(user) {
-  return `a-user-role is-${user.primary_role} ${
-    user.joining_status === 'new-user' ? 'is-new-user' : ''
-  }`
-}
+export default function userIconFrameClass(user = {}) {
+  const primaryRoleClass = user.primary_role ? `is-${user.primary_role}` : ''
+  const newUserClass = user.joining_status === 'new-user' ? 'is-new-user' : ''
+  return ['a-user-role', primaryRoleClass, newUserClass].filter(Boolean).join(' ')
+}
  1. 可能なら呼び出し側を明確にする(ListComment 側)
  • A: comment から必要最小限のフィールドだけ渡す
-<span className={userIconFrameClass(comment)}>
+<span
+  className={userIconFrameClass({
+    primary_role: comment.primary_role,
+    joining_status: comment.joining_status
+  })}
+>
  • もしくは comment に user オブジェクトが含まれていれば user を渡す:
-<span className={userIconFrameClass(comment)}>
+<span className={userIconFrameClass(comment.user || {})}>

理由: ユーティリティを防御的にすることで将来の呼び出しミスを防ぎつつ、呼び出し側で可能なら正しい user 形状を渡すのが最も安全です。

該当ファイル:

  • app/javascript/components/ListComment.jsx(userIconFrameClass(comment) の箇所)
  • app/javascript/user-icon-frame-class.js(ユーティリティ本体)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<span className={userIconFrameClass(comment)}>
<img className="a-user-icon" src={comment.user_icon}/>
</span>
export default function userIconFrameClass(user = {}) {
const primaryRoleClass = user.primary_role ? `is-${user.primary_role}` : ''
const newUserClass = user.joining_status === 'new-user' ? 'is-new-user' : ''
return ['a-user-role', primaryRoleClass, newUserClass].filter(Boolean).join(' ')
}
🤖 Prompt for AI Agents
app/javascript/components/ListComment.jsx lines 24-26: ListComment currently
calls userIconFrameClass(comment) but the utility expects a user-shaped object
(accesses primary_role / joining_status). Update the utility
(app/javascript/user-icon-frame-class.js) to be defensive: accept either a user
or a comment object, resolve const user = (arg && arg.user) ? arg.user : arg,
use optional chaining (user?.primary_role, user?.joining_status) and safe
defaults when building the class string so missing fields don’t throw;
optionally, if you can change the caller, update ListComment.jsx to pass
comment.user when present (or pass only the minimal fields needed) to make the
intent explicit.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai

指摘点を以下のように修正しました。

  • userIconFrameClass() のクラス生成部をスペースで連結するようにリファクタリング
  • userIconFrameClass() の引数をprimary_rolejoining_status の2つに分けて明確化
  • userIconFrameClass() の呼び出し箇所は全て引数有りなのでデフォルト値設定は無し

確認お願いします。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

@karlley 修正内容を確認させていただきます。現在のコードの状態を確認します。


🏁 Script executed:

#!/bin/bash
# Check the current implementation of userIconFrameClass
echo "=== Current userIconFrameClass implementation ==="
cat app/javascript/user-icon-frame-class.js

echo
echo "=== All call sites of userIconFrameClass ==="
rg -n -A2 -B1 'userIconFrameClass\(' --type=js --type=jsx

echo
echo "=== Verify ListComment.jsx current state ==="
cat app/javascript/components/ListComment.jsx | grep -n -A3 -B3 'userIconFrameClass'

Length of output: 1333


🏁 Script executed:

#!/bin/bash
# Check all JavaScript files that might contain userIconFrameClass calls
echo "=== Search for userIconFrameClass usage in all JS files ==="
find . -name "*.js" -o -name "*.jsx" | xargs grep -l "userIconFrameClass" 2>/dev/null

echo
echo "=== Check each file that uses userIconFrameClass ==="
for file in $(find . -name "*.js" -o -name "*.jsx" | xargs grep -l "userIconFrameClass" 2>/dev/null); do
  echo "--- $file ---"
  grep -n -A3 -B1 "userIconFrameClass" "$file"
  echo
done

Length of output: 4304


@karlley 修正確認完了です!素晴らしい対応をありがとうございます。

すべての修正点が適切に実装されています:

  1. 関数シグネチャの明確化 - userIconFrameClass(primaryRole, joiningStatus) として2つの引数に分離

  2. 全呼び出し箇所の更新 - 5つのコンポーネントすべてで正しく更新されています:

    • Notifications.jsx: notification.sender.primary_role, notification.sender.joining_status
    • ListComment.jsx: comment.primary_role, comment.joining_status
    • Report.jsx: report.user.primary_role, report.user.joining_status
    • User.jsx: user.primary_role, user.joining_status (2箇所)
  3. クリーンな実装 - filter(Boolean).join(' ') による空文字列の除去とスペース連結

特に良い点:

  • 型安全性の向上:何が期待されるかが明確
  • 可読性の向上:引数から処理内容が推測しやすい
  • 一貫性:全コンポーネント間で統一された呼び出し方法

元々の問題(comment オブジェクトを user 前提の関数に渡す問題)が完全に解決されました。


🧬 Code Graph Analysis Results

Filename: app/javascript/user-icon-frame-class.js
Lines: 1-5

export default function userIconFrameClass(primaryRole, joiningStatus) {
  const primaryRoleClass = primaryRole ? `is-${primaryRole}` : '';
  const newUserClass = joiningStatus === 'new-user' ? 'is-new-user' : ''
  return ['a-user-role', primaryRoleClass, newUserClass].filter(Boolean).join(' ');
}

If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
app/javascript/user-icon-frame-class.js (1)

2-3: 微調整提案: 入力の緩やかな正規化(大文字・未定義ケースの吸収)

API契約が安定していれば不要ですが、万一 StudentNEW-USER のような大文字混在値が来ても期待クラスを出せるよう軽く正規化しておくと堅牢です。

-export default function userIconFrameClass(primaryRole, joiningStatus) {
-  const primaryRoleClass = primaryRole ? `is-${primaryRole}` : '';
-  const newUserClass = joiningStatus === 'new-user' ? 'is-new-user' : ''
+export default function userIconFrameClass(primaryRole, joiningStatus) {
+  const normalizedRole = typeof primaryRole === 'string' ? primaryRole.toLowerCase() : ''
+  const normalizedStatus = typeof joiningStatus === 'string' ? joiningStatus.toLowerCase() : ''
+  const primaryRoleClass = normalizedRole ? `is-${normalizedRole}` : ''
+  const newUserClass = normalizedStatus === 'new-user' ? 'is-new-user' : ''
   return ['a-user-role', primaryRoleClass, newUserClass].filter(Boolean).join(' ');
 }
app/javascript/components/ListComment.jsx (1)

24-28: 追加で前提となる userIconFrameClass の定義と ListComment.jsx の先頭部分を確認しました。userIconFrameClass が渡された第1引数(role)と第2引数(joiningStatus)をそのまま扱う実装で、undefined に対するフォールバックは行われていませんでした。 また、ListComment コンポーネント内では、API から受け取る comment オブジェクトに comment.primary_role / comment.joining_status は含まれず、ネストされた comment.user.primary_role / comment.user.joining_status だけが存在します。

これにより、常に comment.primary_role が undefined となって is-undefined クラスが生成されてしまう懸念が確認できました。以下のようにフォールバックを入れることで、API レスポンスのどちらの形状にも対応でき、安全性が向上します。

  • app/javascript/components/ListComment.jsx: userIconFrameClass 呼び出し部
    - className={userIconFrameClass(
    -   comment.primary_role,
    -   comment.joining_status
    - )}
    + className={userIconFrameClass(
    +   comment.primary_role ?? comment.user?.primary_role,
    +   comment.joining_status ?? comment.user?.joining_status
    + )}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 95980fe and 77daacd.

📒 Files selected for processing (5)
  • app/javascript/components/ListComment.jsx (2 hunks)
  • app/javascript/components/NotificationsBell/Notifications.jsx (2 hunks)
  • app/javascript/components/Report.jsx (2 hunks)
  • app/javascript/components/User.jsx (3 hunks)
  • app/javascript/user-icon-frame-class.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/javascript/components/NotificationsBell/Notifications.jsx
  • app/javascript/components/Report.jsx
  • app/javascript/components/User.jsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js

⚙️ CodeRabbit Configuration File

**/*.js: - どうしても避けられない時以外に新規にVue.js, Reactのコードを追加しない。

  • fetchメソッドの代わりにrequest.jsを使う。

Files:

  • app/javascript/user-icon-frame-class.js
🧬 Code Graph Analysis (1)
app/javascript/components/ListComment.jsx (1)
app/javascript/user-icon-frame-class.js (1)
  • userIconFrameClass (1-5)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build_and_test
🔇 Additional comments (2)
app/javascript/user-icon-frame-class.js (1)

1-5: バニラJS化+2引数APIはシンプルで妥当です

  • ベースクラス固定+条件付きクラスを filter(Boolean).join(' ') で構築しており、期待仕様(a-user-role / is- / is-new-user)に合致しています。
app/javascript/components/ListComment.jsx (1)

2-2: default import への移行はOKです

パス・名前の更新が user-icon-frame-class.js の default export と整合しています。

@karlley karlley self-assigned this Aug 19, 2025
@karlley karlley force-pushed the chore/convert-user-icon-frame-class-to-vanilla-js branch from 77daacd to 6fa08dc Compare August 25, 2025 21:01
@karlley
Copy link
Copy Markdown
Contributor Author

karlley commented Aug 26, 2025

@kitarou888
お疲れさまです!
レビューをお願いしたいのですが対応可能でしょうか?

@kitarou888
Copy link
Copy Markdown
Contributor

@karlley
レビュー依頼ありがたいのですが、現在本番環境で起こしてしまっている不具合(検索できない問題)の対応を優先して進めていまして、そちらが片付いての対応でもよければ対応したいと思います!(時期未定ですが来週以降に長引く恐れ有)

取り組み時期未定でお待ちいただくか、他の方に依頼されるか、すみませんがご検討いただければと思います🙏

@karlley
Copy link
Copy Markdown
Contributor Author

karlley commented Aug 29, 2025

@kitarou888

返信遅くなりました💦

取り組み時期未定でお待ちいただくか、他の方に依頼されるか、すみませんがご検討いただければと思います🙏

レビューは全く急いでいませんので、kitarouさんの作業ペースで構いませんのでレビューお願いしたいです🙇‍♂️
よろしくお願いします!

@kitarou888
Copy link
Copy Markdown
Contributor

@karlley
了解しました!
では少しの間お待たせしてしまうかと思いますが、現在の不具合が完了次第取り組ませていただきます🙆‍♂️

@karlley karlley requested a review from kitarou888 September 7, 2025 22:01
Copy link
Copy Markdown
Contributor

@kitarou888 kitarou888 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

動作確認はできていませんが、コードのみ確認させていただきました🙏

動作確認ですが、現在私のPCリソースの関係でローカル環境を正常に開くことが難しいため、大変申し訳ないのですがもう数日お待ちいただけますと幸いです🙇‍♂️

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

元ファイルは引数にuserを受け取っていましたが、本ファイルではロールとステータスの2つをそれぞれ受け取るようにした理由はなんでしょうか??

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

引数がuser になっていましたが、実際の呼び出しの引数はUserIconFrameClass(comment)UserIconFrameClass(notification.sender) のようになっておりuser という変数名が適切では無いと感じたためです。
引数を2つに分けることで呼び出し時の引数を明確にすることを意図していました。

Comment on lines +28 to +32
<div className={`users-item__inner a-card`}>
<div
className={`users-item__inner a-card ${userIconFrameClass(
user.primary_role,
user.joining_status
)}`}>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

変更元ではなかったクラスを新たに追加している理由は何でしょうか??

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

クラスを追加する要素を間違えていました...
修正いたします!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

修正いたしました!

Copy link
Copy Markdown
Contributor Author

@karlley karlley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

レビューありがとうございます!
コメント追加しました。

大変申し訳ないのですがもう数日お待ちいただけますと幸いです🙇‍♂️

急いでいないので問題ないです🙆‍♂️

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

引数がuser になっていましたが、実際の呼び出しの引数はUserIconFrameClass(comment)UserIconFrameClass(notification.sender) のようになっておりuser という変数名が適切では無いと感じたためです。
引数を2つに分けることで呼び出し時の引数を明確にすることを意図していました。

Comment on lines +28 to +32
<div className={`users-item__inner a-card`}>
<div
className={`users-item__inner a-card ${userIconFrameClass(
user.primary_role,
user.joining_status
)}`}>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

クラスを追加する要素を間違えていました...
修正いたします!

@tyrrell-IH tyrrell-IH requested a review from kitarou888 October 22, 2025 03:12
@kitarou888
Copy link
Copy Markdown
Contributor

kitarou888 commented Oct 24, 2025

@karlley
すみません、動作確認が大変遅くなりました🙇‍♂️🙇‍♂️

手順どおりの動作を確認できました!
僕が遅くなったばかりにconflictが発生してしまいましたので、こちらのみ対応いただけましたらApproveさせていただきます🙏
お手間をかけさせてしまって本当に申し訳ないです💦

※以下気になった点を挙げておきます

otameshiさんのコメントアイコン

確認手順に直接記載はないところですが、otameshiさんのアイコンなのにis-new-userクラスがないことが気になりました。
(本PRのスコープ外でしたらスルーいただいて問題ないです!)

image

説明文と画像が差すアイコンが異なっている

文章では日報一覧(/reports)で投稿した日報へのコメント数右のアイコンとありましたが、画像では日報リスト左の大きいアイコンを指していましたが、両方同じクラスが設定されていることを確認しましたので、画像差し替え(or文章訂正)まではしていただかなくてよいかなと思います🙆‍♂️

image

@karlley karlley force-pushed the chore/convert-user-icon-frame-class-to-vanilla-js branch from 771a786 to 19199e5 Compare October 26, 2025 21:31
@karlley
Copy link
Copy Markdown
Contributor Author

karlley commented Oct 26, 2025

@kitarou888

動作確認ありがとうございます!
以下対応しました!

確認手順に直接記載はないところですが、otameshiさんのアイコンなのにis-new-userクラスがないことが気になりました。

is-new-user クラスはユーザー登録後、7日以内のユーザーに付与されます。
私の環境ではbundle exec rails db:seed で初期データを再登録した直後(7日以内)であればis-new-user が付与されるのを確認できました。
初回の動作確認から7日以上経っているので表示されてないのかも?と思いました。
お手数ですが再度ご確認いただけないでしょうか?🙇‍♂️

画像差し替え(or文章訂正)まではしていただかなくてよいかなと思います🙆‍♂️

ご指摘ありがとうございます!
確かに画像と異なっていたので以下のように訂正しました。

日報一覧(/reports)で投稿した日報へのコメント数右のアイコン
↓
日報一覧(/reports)で日報リスト左の大きいアイコン

conflictが発生してしまいましたので、こちらのみ対応いただけましたらApproveさせていただきます🙏

コンフリクト解消しました。

お手数ですがご確認よろしくお願いします!

Copy link
Copy Markdown
Contributor

@kitarou888 kitarou888 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コンフリクト対応ありがとうございました!

また以下、

私の環境ではbundle exec rails db:seed で初期データを再登録した直後(7日以内)であればis-new-user が付与されるのを確認できました。

についてご確認いただいているのでしたら私からは言うことはありませんので、Approveさせていただきます🙆‍♂️

@karlley
Copy link
Copy Markdown
Contributor Author

karlley commented Oct 27, 2025

@kitarou888

お忙しい中レビューありがとうございました!

@komagata

メンバーレビューが完了しました。
レビューお願いします。

Copy link
Copy Markdown
Member

@komagata komagata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確認させていただきました。OKです〜🙆‍♂️

@komagata komagata merged commit 16bc809 into main Nov 4, 2025
11 checks passed
@komagata komagata deleted the chore/convert-user-icon-frame-class-to-vanilla-js branch November 4, 2025 22:30
@github-actions github-actions bot mentioned this pull request Nov 4, 2025
16 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants